#ifndef _BASELINE_RANDOM_WALK_H_
#define _BASELINE_RANDOM_WALK_H_

#include <vector>
#include <set>
#include <map>
#include "API.h"

using namespace std;

class BaseCrawler
{
public:
    BaseCrawler(API *network_) : network(network_) {
        //No need to initilize starting point. nodeToExplore handles it.
    }

    void setCostLimit(int costLimit) { network->setCostLimit(costLimit); }
    TIntPr evaluate() { return network->evaluate(); }
    TFltPrV getNodeStatistics() { return nodeRecall; }
    TFltPrV getEdgeStatistics() { return edgeRecall; }
    int getTotalCost() { return network->getTotalCost(); }

    virtual void nextStep();
    virtual void crawl(int cost_limit) { 
        setCostLimit(cost_limit);
        while(network->getTotalCost() < cost_limit)nextStep(); 
    }

protected: //This will be different for more sophisticated random walk
    virtual void updateDiscoveredNode(int discoveredNode) = 0;
    virtual int nodeToExplore() = 0;

    TFltPrV nodeRecall, edgeRecall; //<cost, recall>
    API *network;
};

class BaselineRandomWalk : public BaseCrawler
{
public:
    BaselineRandomWalk(API *network_) : BaseCrawler(network_) {}

protected: //This will be different for more sophisticated random walk
    virtual void updateDiscoveredNode(int discoveredNode);
    virtual int nodeToExplore();

    map<int,int> accessibleNodesByRank; // <rank, NodeID>
    map<int, map<int,int>::iterator> nodePointers; // <NodeID, corresponding node in accesibleNodesByRank> // for fast access in the other map; haven't really used it.
};

class AlwaysTeleportRandomWalk : public BaseCrawler {
public:
    AlwaysTeleportRandomWalk(API *network_) : BaseCrawler(network_) {}
protected:
    virtual void updateDiscoveredNode(int discoveredNode) {} //Don't care
    virtual int nodeToExplore() {
      int nid;
      while (1) {
	nid = network->getTeleportNode();
	if (nid == -1)
	  return -1;
	if (!visited.IsKey(nid))
	  break;
      }
      visited.AddKey(nid);
      return nid;
    }

    THashSet<TInt> visited;
};

#endif
